/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "service_proxy.h"
#include <vector>
#include "common_utils.h"
#include "loghelper.h"
#include "message_option.h"
#include "message_parcel.h"
#include "reader_proxy.h"
#include "se_service_ipc_interface_code.h"

namespace OHOS {
namespace SE {
namespace OMAPI {
ErrorCode ServiceProxy::GetReaders(std::vector<std::string> &readers)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    readers = std::vector<std::string>();
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("GetReaders Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READERS),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[SessionProxy::GetReaders] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READERS, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int statusCode = reply.ReadInt32();
    if (!reply.ReadStringVector(&readers)) {
        ErrorLog("[SessionProxy::GetReaders] Failed to ReadStringVector to result, statusCode = %{public}d",
            statusCode);
    } else {
        InfoLog("[SessionProxy::GetReaders] send request(%{public}d) with Res(%{public}d) success.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READERS, res);
    }
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ServiceProxy::GetReaderInterface(const std::string &readerName, sptr<ISecureElementReader> &iface)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("GetReaderInterface Write interface token error");
        iface = nullptr;
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    data.WriteString(readerName);
    int res = Remote()->SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READER_IFACE),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ServiceProxy::GetReaderInterface] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READER_IFACE, res);
        iface = nullptr;
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }

    sptr<OHOS::IRemoteObject> object = reply.ReadRemoteObject();
    int statusCode = reply.ReadInt32();
    if (object == nullptr) {
        ErrorLog("[ServiceProxy::GetReaderInterface] send request(%{public}d) with State(%{public}d) success.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_GET_READER_IFACE, statusCode);
        iface = nullptr;
    } else {
        if (!iface) {
            InfoLog("[ServiceProxy::GetReaderInterface] new iface");
            iface = new ReaderProxy(object);
        } else {
            ErrorLog("[ServiceProxy::GetReaderInterface] new iface before not null error");
        }
    }
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ServiceProxy::IsNfcEventAllowed(const std::string &readerName,
                                          const std::string &aid,
                                          std::vector<std::string> bundleNames,
                                          std::vector<bool> &allowedStatus)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    allowedStatus = std::vector<bool>();
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("IsNfcEventAllowed Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    data.WriteString(readerName);
    data.WriteString(aid);
    data.WriteStringVector(bundleNames);
    int res = Remote()->SendRequest(
        static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_SERVICE_IS_NFC_EVENT_ALLOWED), data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ServiceProxy::IsNfcEventAllowed] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_IS_NFC_EVENT_ALLOWED,
            res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }

    int statusCode = reply.ReadInt32();
    if (!reply.ReadBoolVector(&allowedStatus)) {
        ErrorLog("[ServiceProxy::IsNfcEventAllowed] ReadBoolVector failed");
    } else {
        InfoLog("[ServiceProxy::IsNfcEventAllowed] send request(%{public}d) with Res(%{public}d) success.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_IS_NFC_EVENT_ALLOWED, res);
    }
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ServiceProxy::Shutdown()
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("Shutdown Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int res = Remote()->
        SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_SERVICE_SHUTDOWN), data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ServiceProxy::RegisterCallerListener] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_REGISTER_CALLER_LISTENER, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}

ErrorCode ServiceProxy::RegisterCallerListener(const sptr<IRemoteObject> &obj)
{
    MessageParcel data;
    MessageParcel reply;
    MessageOption option(MessageOption::TF_SYNC);
    if (!data.WriteInterfaceToken(GetDescriptor())) {
        ErrorLog("Shutdown Write interface token error");
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    data.WriteRemoteObject(obj);
    int res = Remote()->
        SendRequest(static_cast<uint32_t>(SeServiceIpcInterfaceCode::COMMAND_SERVICE_REGISTER_CALLER_LISTENER),
        data, reply, option);
    if (res != ERR_NONE) {
        ErrorLog("[ServiceProxy::RegisterCallerListener] send request(%{public}d) with Res(%{public}d) fail.",
            SeServiceIpcInterfaceCode::COMMAND_SERVICE_REGISTER_CALLER_LISTENER, res);
        return ErrorCode::SE_IPC_TOKEN_ERROR;
    }
    int statusCode = reply.ReadInt32();
    return CommonUtils::IntToErrorCode(statusCode);
}
}  // namespace OMAPI
}  // namespace SE
}  // namespace OHOS